//复杂度O(n + m)//将有向图变为拓扑图(有向无环图)
int dfn[N], low[N], timestamp;
bool in_stk[N];
int id[N], scc_cnt, Size[N];//每个强连通分的节点个数
int dout[N];//记录所有点(包括缩点)的出度
stack<int>stk; //栈代表当前未被搜完的强连通分量的所有点
void tarjan(int u)//tarjan完是逆dfs序
{
    dfn[u] = low[u] = ++ timestamp; //u的时间戳
    stk.push(u), in_stk[u] = true;//把当前点加到栈中  当前点在栈中
    for (int i = h[u]; i != -1; i = ne[i])
    {
        int j = e[i];
        if (!dfn[j])
        {
            tarjan(j);
            low[u] = min(low[u], low[j]);
        }
        else if (in_stk[j]) low[u] = min(low[u], dfn[j]);
    }
    if (dfn[u] == low[u])
    {
        ++ scc_cnt;//强连通分量总数+1
        int y;
        do {
            y = stk.top();
            stk.pop();
            in_stk[y] = false;
            id[y] = scc_cnt;
            Size[scc_cnt] ++ ;//第scc_cnt个连通块点数+1
        } while (y != u);
    }
}

for (int i = 1; i <= n; i ++ )
    if (!dfn[i])
        tarjan(i);